<template>
  <div class="calculator-index">
    <div v-if="rwDispatcherState === 'write'" :class="isShowModel?'focus':status === 'error'?'error':''" :style="{'width':width}">
      <div class="write-box" @click="showModal">
        <el-tag
          v-for="(tag,index) in calculatorList"
          :key="tag[dataConfig.key]+index"
        >
          {{ tag[dataConfig.value] }}
        </el-tag>
      </div>
      <calculator-model v-show="isShowModel" v-bind="$attrs" @on-change="change" />
    </div>
    <div v-else :style="{'width':width}" @click="showModal">
      {{ label }}
    </div>
    <p v-show="status === 'error'" class="error-msg">{{ errorMsg }}</p>
  </div>
</template>
<script>
import calculatorModel from './model.vue'
export default {
  name: 'ZlstCalculator',
  components: {
    calculatorModel
  },
  props: {
    // 数据格式
    dataConfig: {
      type: Object,
      default() {
        return {
          type: 'type',
          id: 'id',
          key: 'fieldKey',
          value: 'name'
        }
      }
    },
    // 默认值
    defaultValue: {
      type: Array,
      default() {
        return []
      }
    },
    // 样式宽度
    width: {
      type: String,
      default: '100%'
    },
    // 默认公式
    defaultLabel: {
      type: String,
      default: '11'
    },
    // 输入状态
    rwDispatcherState: {
      type: String,
      default: 'write'
    }
  },
  data() {
    return {
      errorMsg: '错误提示',
      status: 'info', // 校验状态
      label: '', // 非编辑状态下的公式
      isShowModel: false, // 展示操作框
      calculatorList: [] // 公式数据
    }
  },
  watch: {
    defaultLabel: {
      immediate: true,
      handler(val) {
        this.label = val
      }
    },
    defaultValue: {
      immediate: true,
      handler(val) {
        this.calculatorList = val
      }
    },
    isShowModel(val) {
      if (!val) {
        const gongshi = this.calculatorList.map(item => {
          return item.type === 'param' ? `{${item[this.dataConfig.value]}}` : item[this.dataConfig.value]
        }).join('')
        const valid = this.validate(gongshi)
        if (valid === '校验通过') {
          this.status = 'info'
        } else {
          this.status = 'error'
          this.errorMsg = valid
        }
      }
    }
  },
  methods: {
    // 校验运算式子
    validate(string) {
      if (string === '') {
        return '未填写公式'
      }
      if (/^[\)\.\÷\+\-\*\/]/.test(string)) {
        return '运算符或后括号开头'
      }
      if (/^[\)\.\÷\+\-\*\/]/.test(string)) {
        return '运算符或后括号开头'
      }
      if (/[\(\.\÷\+\-\*\/]$/.test(string)) {
        return '运算符或前括号结尾'
      }
      if (/[\.\÷\+\-\*\/]{2,}/.test(string)) {
        return '运算符连续'
      }
      if (/\}\{/.test(string)) {
        return '数据项连续'
      }
      if (/\([\)\÷\+\-\*\/]/.test(string)) {
        return '(后面是运算符或者)'
      }
      if (/[\.\÷\+\-\*\/]\)/.test(string)) {
        return ')前面是运算符'
      }
      if (!/[\.\÷\+\-\*\/]\(/.test(string) && !/^\(/.test(string) && /\(/.test(string)) {
        return '(前面不是运算符' // 且(不是开头
      }
      if (!/\)[\.\÷\+\-\*\/]/.test(string) && !/\)$/.test(string) && /\)/.test(string)) {
        return ')后面不是运算符' // 且)不是结尾
      }
      if (/[0-9]\{/.test(string)) {
        return '数据项前面不能为数字'
      }
      if (/\}[0-9]/.test(string)) {
        return '数据项后面不能为数字'
      }
      var stack = []
      for (var i = 0, item; i < string.length; i++) {
        item = string.charAt(i)
        if (item === '(') {
          stack.push('(')
        } else if (item === ')') {
          if (stack.length > 0) {
            stack.pop()
          } else {
            return ')之前没有('
          }
        }
      }
      if (stack.length !== 0) {
        return '()个数不等'
      }
      return '校验通过'
    },
    // 打开计算器
    showModal() {
      this.isShowModel = !this.isShowModel
    },
    // 改变值
    change() {
      // arguments: operate, type, id, key, value
      // console.log(arguments)
      switch (arguments[0]) {
        case 'push':
          this.calculatorList.push({
            [this.dataConfig.type]: arguments[1],
            [this.dataConfig.id]: arguments[2],
            [this.dataConfig.key]: arguments[3],
            [this.dataConfig.value]: arguments[4]
          })
          break
        case 'clear':
          this.calculatorList = []
          break
        case 'delete':
          this.calculatorList.pop()
          break
        default:
          break
      }
    }
  }
}
</script>
<style lang="scss">
.calculator-index{
  padding: 0 10px;
  & > div{
    border: 1px solid #DCDFE6;
    border-radius: 4px;
    min-height: 32px;
    line-height: 30px;
    padding: 0 10px;
    cursor: pointer;
    position: relative;
    .write-box{
      width: 100%;
      height: 100%;
      min-height: 32px;
      span.el-tag{
        margin-right: 4px;
      }
    }
    &.focus{
      border-color: #2993FF;
      -webkit-box-shadow: 0px 0px 8px 0px rgba(41,147,255,0.3);
      box-shadow: 0px 0px 8px 0px rgba(41,147,255,0.3);
    }
    &.error{
      border-color: #f56c6c;
      -webkit-box-shadow: 0px 0px 8px 0px rgba(245, 108, 108, 0.3);
      box-shadow: 0px 0px 8px 0px rgba(245, 108, 108, 0.3);
    }
  }
  .error-msg{
    color: #f56c6c;
    font-size: 12px;
    line-height: 16px;
  }
}
</style>
